package website.seamonster.ethegg.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import website.seamonster.ethegg.dataobject.Account;
import website.seamonster.ethegg.dataobject.Transaction;
import website.seamonster.ethegg.dataobject.TxReq;
import website.seamonster.ethegg.dataobject.User;
import website.seamonster.ethegg.enums.TxReqStatusEnum;
import website.seamonster.ethegg.enums.TxStatusEnum;
import website.seamonster.ethegg.exception.EthException;
import website.seamonster.ethegg.repository.*;
import website.seamonster.ethegg.service.background.BuyEggService;
import website.seamonster.ethegg.service.background.TransactionService;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by 罗海量
 * 2018-07-22 00:02
 */
@lombok.extern.slf4j.Slf4j
@Service
public class TxReqService {
    @Autowired
    private TxReqRepository txReqRepository;
    @Autowired
    private BuyEggService buyEggService;
    @Autowired
    private TransactionRepository txRepository;
    @Autowired
    private TransactionService txService;

    public void createTx(String clientId, String buyerUserId, User prUser, Integer buyCnt){
        TxReq req = new TxReq();
        req.setClientId(clientId);
        req.setUserId(buyerUserId);
        if (prUser!=null) {
            req.setPrCode(prUser.getPrCode());
            req.setPrUserId(prUser.getId());
        }
        if (buyCnt != null) {
            req.setBuyCnt(buyCnt);
        }
        txReqRepository.save(req);
    }

    //根据clientId查询交易状态
    public TxReq getTxReqByClientId(String clientId){
        Timestamp ts = new Timestamp(System.currentTimeMillis());
        TxReq txreq = txReqRepository.findFirstByClientIdAndAndCreateTimeBefore(clientId, ts);
        return txreq;
    }

    //按顺序处理交易请求
    @Transactional
    public void handleTx(){
        TxReq req = txReqRepository.findFirstByTxStatusOrderByIdAsc(TxReqStatusEnum.WAIT.getCode());

        //如果没有待处理的交易请求
        if (req == null) {
            log.info("没有交易");
            return;
        }else{
            List<Transaction> txList = txRepository.findAllByTxReqId(req.getId());
            if (txList==null || txList.size()==0){ //未处理的交易请求
                //买蛋(注意有可能买多只蛋)
                int buyNum = req.getBuyCnt();
                for (int i=0; i< buyNum; i++){
                    try {
                        buyEggService.buyEgg(req.getId(), req.getUserId(), req.getPrCode(), req.getPrUserId());
                    } catch (EthException e) {
                        //创建一条交易失败记录
                        txService.createFailTx(req, e.getCode(), e.getMessage());
                    }
                }
            } else {
                //查看交易情况，修改交易请求状态
                List<Transaction> txWaits = txList.stream().filter(tx -> TxStatusEnum.WAIT.getCode().equals(tx.getTxStatus())).collect(Collectors.toList());
                List<Transaction> txSussesss = txList.stream().filter(tx -> TxStatusEnum.SUCCESS.getCode().equals(tx.getTxStatus())).collect(Collectors.toList());
                List<Transaction> txFails = txList.stream().filter(tx -> TxStatusEnum.FAIL.getCode().equals(tx.getTxStatus())).collect(Collectors.toList());
                if (txWaits == null || txWaits.size()==0){ //已经没有等待状态的交易，全部交易都是成功或失败
                    if (txSussesss == null || txSussesss.size()==0) {
                        //1条成功的也没有，整个失败
                        req.setTxStatus(TxReqStatusEnum.FAIL.getCode());
                    } else {
                        //有部分成功的也叫成功
                        req.setTxStatus(TxReqStatusEnum.SUCCESS.getCode());
                    }
                    txReqRepository.save(req);
                }

            }
        }
    }

    /**
     * 用户其他正在请求的交易中，购买的蛋数
     * @param userId
     * @return
     */
    public Integer getBuyingEggNumsByUserId(String userId){
        Integer buyingCount = txReqRepository.getBuyingCountByUserId(userId, TxReqStatusEnum.WAIT.getCode());
        if (buyingCount==null){
            return 0;
        }else {
            return buyingCount;
        }
    }
}
